package main

import (
	"github.com/garyburd/redigo/redis"
	"strings"
	"sync"
	"redistools"
)

func main() {
	//c, err := redis.Dial("tcp", "127.0.0.1:6379")
	//if err != nil {
	//	panic(err)
	//}
	//queryTotalPrefixCount("upm_stable", c)
	//queryNotMatch("stable_upm_service", c)
	deleteMatchPrefix("stable_upm_service")
	println("process finish")
}
func queryTotalPrefixCount(prefix string, c redis.Conn) (count int) {
	//values, _ := redis.Values(c.Do("SCAN", "0"))
	start := 0
	count = 0
	for {
		values, _ := redis.Values(c.Do("SCAN", start, "MATCH", prefix+"*"))
		var keys []string
		start, _ = redis.Int(values[0], nil)
		keys, _ = redis.Strings(values[1], nil)
		if len(keys) > 0 {
			count += 1
		} else {
			break
		}
		if count%100 == 0 {
			println(count)
		}
	}
	return
}
func queryNotMatch(prefix string, c redis.Conn) (count int) {
	start := 2
	count = 0
	for {
		values, _ := redis.Values(c.Do("SCAN", start))
		var keys []string
		start, _ = redis.Int(values[0], nil)
		keys, _ = redis.Strings(values[1], nil)
		if len(keys) > 0 {
			for _, v := range keys {
				if (!strings.Contains(v, prefix)) {
					println(v)
				}
			}
		} else {
			break
		}
	}
	return
}

const (
	MAX_CONCURRENCY = 100
)

var tmpChan = make(chan struct{}, MAX_CONCURRENCY)
var waitGroup sync.WaitGroup

func deleteMatchPrefix(prefix string) {
	start := 5
	keyArray := make([]string, 20000)
	count := 0
	for {
		if (count >= 15000) {
			deleteCount := 0
			batchDelete := 1000
			for i := count; i >= 0; i-- {
				if (i > 0 && i%batchDelete == 0) {
					waitGroup.Add(1)
					tmpChan <- struct{}{}
					count -= batchDelete
					deleteCount += batchDelete
					deleteStart := deleteCount - batchDelete
					go deleteKey(keyArray[deleteStart:deleteCount])
				}
			}
			if count-deleteCount > 0 {
				waitGroup.Add(1)
				tmpChan <- struct{}{}
				go deleteKey(keyArray[deleteCount:count])
			}
			waitGroup.Wait()
			count = 0
		}
		c := redistools.GetConnection()
		values, err := redis.Values(c.Do("SCAN", start, "COUNT", 200))
		if err != nil {
			panic(err)
		}
		c.Close()
		var keys []string
		start, _ = redis.Int(values[0], nil)
		keys, _ = redis.Strings(values[1], nil)
		if len(keys) > 0 {
			for _, v := range keys {
				if (strings.Contains(v, prefix)) {
					keyArray[count] = v
					count += 1
				}
			}
		} else {
			break
		}
	}
	if count > 0 {
		waitGroup.Add(1)
		tmpChan <- struct{}{}
		count -= 1
		go deleteKey(keyArray[0:count])
	}

	waitGroup.Wait()
	return
}
func deleteKey(keys []string) {
	c := redistools.GetConnection()
	if len(keys) > 0 {
		c.Do("DEL", keys)
		for _, v := range keys {
			c.Send("DEL",v)
			println("delete " + v)
		}
		c.Flush()
	}
	defer func() {
		c.Close()
		<-tmpChan
		waitGroup.Done()
	}()
}
